
#include <string.h>
#include "ka-system/uuid.h"

using namespace ka;

UUID::UUID(const char *cstr) {
    size_t l = strlen(cstr);
    if (l != 36 || !_setMsb(cstr) || !_setLsb(cstr)) {
        _setNil();
    }
}

bool UUID::operator==(const UUID &u) const {
    return _msb==u._msb
    && _lsb==u._lsb;
}

void UUID::_setNil() {
    _msb = UINT64_C(0);
    _lsb = UINT64_C(0);
}

static int32_t _hex4bit(char c) {
    int32_t v = -1;
    if (c>='0' && c<='9')
        v = c - '0';
    else if (c>='a' && c<='f')
        v = 10 + c - 'a';
    else if (c>='A' && c<='F')
        v = 10 + c - 'A';
    return v;
}

static int32_t _hex16bit(const char *cp) {
    int32_t v = _hex4bit(cp[0]);
    v = (v << 4) | _hex4bit(cp[1]);
    v = (v << 4) | _hex4bit(cp[2]);
    v = (v << 4) | _hex4bit(cp[3]);
    return v;
}

static const int _MSB_IDX[4] = {0, 4, 9, 14};
static const int _LSB_IDX[4] = {19,24,28,32};

static bool _hex64idx(const char *cstr, const int idx[], uint64_t *dst) {
    uint64_t b = UINT64_C(0);
    bool r = true;
    
    for (int i=0; i<4; ++i) {
        int32_t h = _hex16bit(&cstr[idx[i]]);
        r = r && (h >= 0);
        b = (b << 16) | (0xffff & h);
    }
    
    if (r && dst) {
        *dst = b;
    }
    
    return r;
}


bool UUID::_setMsb(const char *cstr) {
    return _hex64idx(cstr, _MSB_IDX, &_msb);
}

bool UUID::_setLsb(const char *cstr) {
    return _hex64idx(cstr, _LSB_IDX, &_lsb);
}